package utils

import (
	"fmt"
	"sync"
)

type verbosityBit int

const (
	// Precent SHow Precent
	Precent verbosityBit = 1 << iota
	// Current SHow Current progress
	Current
	// Total Show Total
	Total
)

// All show all
const All = Precent | Current | Total

// Progress display control
type Progress struct {
	Prompt    string
	Verbosity verbosityBit
	Total     int
	Every     int
	now       int
	show      int
	lock      sync.Mutex
}

// NewProgress new progress with default set
func NewProgress(p string, t int) *Progress {
	return &Progress{
		Prompt:    p,
		Verbosity: All,
		Total:     t,
		Every:     1000,
	}
}

//Init initial
func (p *Progress) Init() {
	fmt.Printf("%s\033[s", p.Prompt)
	p.now = 0
	p.show = 0
}

//Done one step
func (p *Progress) Done() {
	p.lock.Lock()
	defer p.lock.Unlock()
	p.now++
	if p.now*p.Every > p.show*p.Total {
		p.show++
		fmt.Printf("\033[u\033[K(")
		if p.Verbosity&Current != 0 {
			fmt.Printf(" %8d", p.now)
		}
		if p.Verbosity&Total != 0 {
			total := fmt.Sprintf("%d", p.Total)
			space := "          "
			total = total + space[len(total):]
			fmt.Printf("/%s ", total)
		}
		if p.Verbosity&Precent != 0 {
			var k = 0
			for i := p.Every; i > 0; i /= 10 {
				k++
			}
			var fm string
			if k < 3 {
				fm = " %2f"
			} else {
				fm = fmt.Sprintf(" %%2.%df", k-3)
			}

			fmt.Printf(fm, float64(p.now)/float64(p.Total)*100.)
			fmt.Printf("%% )")
		} else {
			fmt.Printf(" )")
		}

	}
}

// End finish
func (p *Progress) End() {
	fmt.Println("")
}
